<template>
  <el-button v-if="!this.snapshotMode" text
             type="primary"
             size="small"
             icon="el-icon-plus"
             @click="$refs.crud.rowAdd()">
    增加参数
  </el-button>
  <avue-crud ref="crud"
             v-show="modelValue.length > 0"
             :data="modelValue"
             v-model="form"
             :option="option"
             :before-open="beforeOpen"
             @row-save="rowSave"
             @row-update="rowUpdate"
             @row-del="rowDel">
    <template #specEnum-form="{}">
      <function-enum v-model="enumsData" :snapshot-mode="snapshotMode"></function-enum>
    </template>
    <template #specStruct-form="{}">
      <function-struct v-model="structData" :snapshot-mode="snapshotMode"></function-struct>
    </template>
    <template #fieldType="{ row }">
      <el-tag>{{ row.fieldType }}</el-tag>
    </template>
  </avue-crud>
</template>
<script>
import func from "@/utils/func";

export default {
  name: "functionStructFull",
  props: {
    modelValue: {
      type: Object,
      default: () => ([])
    },
    snapshotMode: {
      type: Boolean,
      default: false
    }
  },
  data() {
    const validateMin = (rule, value, callback) => {
      this.validateSpecMin(rule, value, callback);
    };
    const validateMax = (rule, value, callback) => {
      this.validateSpecMax(rule, value, callback);
    };
    const validateStep = (rule, value, callback) => {
      this.validateSpecStep(rule, value, callback);
    };
    return {
      form: {},
      enumsData: [],
      structData: [],
      option: {
        size: 'small',
        header: false,
        editBtn: true,
        delBtn: true,
        viewBtn: false,
        labelWidth: 100,
        menuWidth: 130,
        dialogWidth: 600,
        column: [
          {
            label: "参数名称",
            labelTip: "支持中文、大小写字母、日文、数字、短划线、下划线、斜杠和小数点，必须以中文、英文或数字开头，不超过 30 个字符",
            prop: "name",
            span: 24,
            rules: [{
              required: true,
              message: "请输入参数名称",
              trigger: "change"
            }],
          },
          {
            label: "标识符",
            labelTip: "支持英文大小写、数字、下划线和短划线，必须以英文或数字开头，不超过 30 个字符",
            prop: "identifier",
            span: 24,
            rules: [{
              required: true,
              message: "请输入标识符",
              trigger: "change"
            }],
          },
          {
            label: "数据类型",
            prop: "fieldType",
            type: "select",
            value: "int32",
            width: 85,
            dicData: [{
              label: 'int32 : 整数型',
              value: 'int32'
            }, {
              label: 'float : 单精度浮点型',
              value: 'float'
            }, {
              label: 'double : 双精度浮点型',
              value: 'double'
            }, {
              label: 'text : 字符串',
              value: 'text'
            }, {
              label: 'enum : 枚举型',
              value: 'enum'
            }, {
              label: 'bool : 布尔型',
              value: 'bool'
            }, {
              label: 'date : 时间型',
              value: 'date'
            }, {
              label: 'array : 数组',
              value: 'array'
            }, {
              label: 'struct : 结构体',
              value: 'struct'
            }],
            span: 24,
            rules: [{
              required: true,
              message: "请选择数据类型",
              trigger: "blur"
            }],
          },
          {
            label: "最小值",
            prop: "specMin",
            type: "number",
            min: -2147483648,
            max: 2147483647,
            display: false,
            hide: true,
            span: 24,
            rules: [{
              required: true,
              validator: validateMin,
              trigger: 'change'
            }]
          },
          {
            label: "最大值",
            prop: "specMax",
            type: "number",
            min: -2147483648,
            max: 2147483647,
            display: false,
            hide: true,
            span: 24,
            rules: [{
              required: true,
              validator: validateMax,
              trigger: 'change'
            }]
          },
          {
            label: "步长",
            prop: "specStep",
            type: "number",
            min: 1,
            max: 2147483647,
            display: false,
            hide: true,
            span: 24,
            rules: [{
              required: true,
              validator: validateStep,
              trigger: 'change'
            }]
          },
          {
            label: "单位",
            prop: "specUnit",
            type: 'select',
            dicUrl: "/blade-system/dict/dictionary-full?code=data_unit",
            props: {
              label: "dictValue",
              value: "dictKey"
            },
            filterable: true,
            display: false,
            hide: true,
            span: 24,
          },
          {
            label: '枚举数据',
            prop: 'specEnum',
            type: 'input',
            span: 24,
            display: false,
            hide: true,
          },
          {
            label: "布尔值 0",
            prop: "specBoolFalse",
            placeholder: '如：关',
            display: false,
            hide: true,
            span: 24,
          },
          {
            label: "布尔值 1",
            prop: "specBoolTrue",
            placeholder: '如：开',
            display: false,
            hide: true,
            span: 24,
          },
          {
            label: "数据长度",
            prop: "specLength",
            type: "number",
            value: 64,
            max: 10240,
            placeholder: '请输入数据长度，最大值为10240',
            display: false,
            hide: true,
            span: 24,
          },
          {
            label: "时间格式",
            prop: "specDateFormat",
            value: "String类型的UTC时间戳（毫秒）",
            disabled: true,
            display: false,
            hide: true,
            span: 24,
          },
          {
            label: "元素类型",
            prop: "specItemType",
            type: "radio",
            value: "int32",
            dicData: [{
              label: 'int32',
              value: 'int32'
            }, {
              label: 'float',
              value: 'float'
            }, {
              label: 'double',
              value: 'double'
            }, {
              label: 'text',
              value: 'text'
            }, {
              label: 'struct',
              value: 'struct'
            }],
            span: 24,
            display: false,
            hide: true,
            rules: [{
              required: true,
              message: "请选择功能类型",
              trigger: "blur"
            }],
          },
          {
            label: "元素个数",
            prop: "specSize",
            type: "number",
            value: 10,
            max: 512,
            placeholder: '请输入元素个数，最大值为512',
            display: false,
            hide: true,
            span: 24,
          },
          {
            label: "结构体",
            prop: "specStruct",
            display: false,
            hide: true,
            span: 24,
          },
        ]
      },
    };
  },
  computed: {},
  watch: {
    'form.fieldType'() {
      const fieldType = this.form.fieldType;
      this.$refs.crud.option.column.filter(item => {
        if (item.prop === 'specMin' || item.prop === 'specMax' || item.prop === 'specStep' || item.prop === 'specUnit') {
          item.display = (fieldType === "int32" || fieldType === "float" || fieldType === "double");
        }
        if (item.prop === 'specEnum') {
          item.display = fieldType === "enum";
        }
        if (item.prop === 'specBoolFalse' || item.prop === 'specBoolTrue') {
          item.display = fieldType === "bool";
        }
        if (item.prop === 'specLength') {
          item.display = fieldType === "text";
        }
        if (item.prop === 'specDateFormat') {
          item.display = fieldType === "date";
        }
        if (item.prop === 'specItemType' || item.prop === 'specSize') {
          item.display = fieldType === "array";
        }
        if (item.prop === 'specStruct') {
          item.display = fieldType === "struct";
        }
      });
    },
    'form.specItemType'() {
      const fieldType = this.form.fieldType;
      if (fieldType !== "array") {
        return;
      }
      const specItemType = this.form.specItemType;
      this.$refs.crud.option.column.filter(item => {
        if (item.prop === 'specStruct') {
          item.display = specItemType === "struct";
        }
      });
    },
  },
  mounted() {
    // 在这里可以安全地进行DOM操作
    this.$nextTick(() => {
      // 代码在这里确保整个视图已经更新完毕
      if (this.snapshotMode) {
        this.$refs.crud.option.editBtn = false;
        this.$refs.crud.option.delBtn = false;
        this.$refs.crud.option.viewBtn = true;
      } else {
        this.$refs.crud.option.editBtn = true;
        this.$refs.crud.option.delBtn = true;
        this.$refs.crud.option.viewBtn = false;
      }
    });
  },
  methods: {
    validateSpecMin(rule, value, callback) {
      value = func.toNumber(value);
      this.validateSpec(rule, value, callback);
      const specMax = func.toNumber(this.form.specMax);
      if (value > specMax) {
        callback(new Error('最小值不能大于最大值'));
        return;
      }
      callback();
    },
    validateSpecMax(rule, value, callback) {
      value = func.toNumber(value);
      this.validateSpec(rule, value, callback);
      const specMin = func.toNumber(this.form.specMin);
      if (value < specMin) {
        callback(new Error('最大值不能小于最大值'));
        return;
      }
      callback();
    },
    validateSpecStep(rule, value, callback) {
      value = func.toNumber(value);
      this.validateSpec(rule, value, callback);
      const specMin = func.toNumber(this.form.specMin);
      const specMax = func.toNumber(this.form.specMax);
      if (value > (specMax - specMin)) {
        callback(new Error('步长不能大于最大值与最小值的差值'));
        return;
      }
      callback();
    },
    validateSpec(rule, value, callback) {
      //数据类型
      const fieldType = this.form.fieldType;
      const numberFieldTypes = ["int32", "float", "double"];
      if (!numberFieldTypes.includes(fieldType)) {
        callback();
        return;
      }
      if (fieldType === 'int32' && !Number.isInteger(value)) {
        callback(new Error('请输入正确的整数类型'));
        return;
      }
      // 单精度浮点型
      if (fieldType === 'float' && !this.checkPrecision(value, 7)) {
        callback(new Error('单精度数值格式错误（小数点有效位为 7 位）'));
        return;
      }
      // 双精度浮点型
      if (fieldType === 'double' && !this.checkPrecision(value, 16)) {
        callback(new Error('双精度数值格式错误（小数点有效位为 16 位）'));
      }
    },
    /**
     * 小数点精度判断
     * @param value
     * @param precision
     * @returns {boolean}
     */
    checkPrecision(value, precision) {
      const valueString = value.toString();
      const decimalPointIndex = valueString.indexOf('.');
      if (decimalPointIndex !== -1) {
        const decimalPartLength = valueString.length - decimalPointIndex - 1;
        if (decimalPartLength > precision) {
          return false;
        }
      }
      return true;
    },
    beforeOpen(done, type) {
      //新增时将enumsData/structData置空
      if (["add"].includes(type)) {
        this.enumsData = [];
        this.structData = [];
      }
      if (["edit", "view"].includes(type)) {
        //编辑查看时将specEnum转换成enumsData
        if (this.form.specEnum.length > 0) {
          this.enumsData = func.keyValueToJsonArray(this.form.specEnum);
        }
        if (this.form.specStruct.length > 0) {
          this.structData = this.form.specStruct;
        }
      }
      done();
    },
    rowSave(form, done, loading) {
      form.id = new Date().getTime();
      if (this.enumsData.length > 0) {
        form.specEnum = func.jsonArrayToKeyValue(this.enumsData);
      }
      if (this.structData.length > 0) {
        form.specStruct = this.structData;
      } else {
        form.specStruct = [];
      }
      loading();
      done(form);
    },
    rowUpdate(form, index, done, loading) {
      if (this.enumsData.length > 0) {
        form.specEnum = func.jsonArrayToKeyValue(this.enumsData);
      }
      if (this.structData.length > 0) {
        form.specStruct = this.structData;
      } else {
        form.specStruct = [];
      }
      loading();
      done(form);
    },
    rowDel(form, index, done) {
      this.$confirm('确定将选择数据删除?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        done(form)
      });
    },
  }
}
</script>
